package com.hontech.dapapp

import android.content.Context
import android.hardware.usb.UsbConstants
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import com.hontech.dapapp.app.AppContext
import com.hontech.dapapp.utils.AppTask
import com.hontech.dapapp.utils.log
import com.hontech.dapapp.utils.runIO

class DapLink {

    companion object {

        init {
            System.loadLibrary("cmsisdap")
        }

        const val VID = 0x0D28
        const val PID = 0x0204
    }

    private external fun download(fd: Int, target: String, path: String, cb: DownloadProgress)

    private external fun downloadWithEp(fd: Int, epIn: Int, epOut: Int, maxPacketSize: Int, target: String, path: String, cb: DownloadProgress)

    private fun deviceInfo(device: UsbDevice) {
        for (i in 0 until device.interfaceCount) {
            val inter = device.getInterface(i)
            log("interface:${inter.interfaceClass} ${inter.name}")
            for (k in 0 until inter.endpointCount) {
                val ep = inter.getEndpoint(k)
                log("ep:${ep.maxPacketSize} ${ep.direction} ${ep.type}")
            }
        }
    }

    private suspend fun openUsb(): UsbDeviceConnection {
        val usbManager = AppContext.getSystemService(Context.USB_SERVICE) as UsbManager
        for (device in usbManager.deviceList.values) {
            if ((device.productId == PID) && (device.vendorId == VID)) {
                deviceInfo(device)
                return open(usbManager, device)
            }
        }
        throw IllegalStateException("没有找到CMSIS DAP Link")
    }

    private suspend fun open(usbManager: UsbManager, device: UsbDevice): UsbDeviceConnection {
        val ret = usbManager.hasPermission(device)
        if (!ret) {
            requestUsbPermission(AppContext, device, usbManager)
        }
        val conn = usbManager.openDevice(device)
        return conn
    }

    suspend fun download(target: String, id: Long, cb: (String) -> Unit) {

        val conn = openUsb()
        try {
            val path = com.hontech.dapapp.utils.download(id)
            cb("固件下载完成开始编程")
            runIO {
                var index: Long = 0
                var length: Long = 0
                var eraseLen: Long = 0
                download(conn.fileDescriptor, target, path, object: DownloadProgress {
                    override fun onProgram(size: Int, time: Int) {
                        index += size
                        AppTask.post { cb("编程中:${index * 100 / length}%") }
                    }

                    override fun onErased(size: Long, time: Int) {
                        eraseLen += size
                        AppTask.post { cb("扇区擦除:${eraseLen}byte") }
                    }

                    override fun onStart(len: Long) {
                        length = len
                    }
                })
            }

        } catch (e: Exception) {
            throw e
        } finally {
            conn.close()
        }
    }
}

interface DownloadProgress {

    fun onStart(len: Long)
    fun onProgram(size: Int, time: Int)
    fun onErased(size: Long, time: Int)
}
